/*
	Copyright (c) 2009-2011, Stefan Webb.

	This file is part of SimpleML. Please read the file "license.txt", 
	which contains the conditions under which this software is distributed.
*/

/*!
	\file error.h
	\author Stefan Webb
	\brief Definition of Error class.
*/

#ifndef ERROR_H
#define ERROR_H

/*! Maximum error string length. */
#define MAXIERRORLENGTH 1024

/*! Structure for a warning. */
struct Warning
{
	// Warning number
	unsigned int number;

	// Warning string. Is not unique for a given warning number (may contain special information like what it was
	// doing when warning was thrown etc.)
	wchar_t* text;
};

/*! \brief This class handles all program errors. 
	One instance is created by default. */
class Error {
public:
	/*! Default constructor */
	Error();

	/*! Default destructor */
	~Error();

	/*! Stream-like operators, to fill error message */
	Error& operator<<(const char*);
	Error& operator<<(const unsigned char*);
	Error& operator<<(const wchar_t*);
	Error& operator<<(const int);
	
	/*! Displays error message with no number (i.e. number is 0), then exits. */
	void exception();

	/*! Displays error message with number, then exits.
		\param number Error number. */
	void exception(unsigned int number);

	/* Display error message with no number (i.e. number is zero), and push onto stack. */
	void warning();

	/*! Display error message with number and push onto stack.
		\param number Error number. */
	void warning(unsigned int number);

	/*! Check if there are warnings on the stack.
		\return Error status. True indicates an error has occurred. */
	bool occurred();

	/*! \brief Get the most recent warning number and message. Pops off stack, so next call will get the 
		one before that, and so on.
		\return Most recent warning. */
	Warning* last();

	/*! \brief Control whether error or warning number is displayed. */
	void toggleDisplayNumber();

	/*! \brief Control whether error message is displayed at all. */
	void toggleDisplay();

	// TODO: Change output of error message. What outputs will I allow? 
	// Perhaps: console, messagebox, and callback function.

	/*! Clear error status */
	void clear();

private:
	/*! Prevent copy-constructor. */
	Error(const Error&);

	/*! Prevent assignment. */
	Error& operator=(const Error&);

	/*! Display error message, and resets error message. 
		\param isWarning Set to true if displaying warning, false if exception. */
	void display(bool isWarning);

	/*! Keep record of whether object has been created */
	static bool isCreated_;

	/*! String containing error message, set through << operators. */
	wchar_t* string_;

	/*! Error message number */
	unsigned int number_;

	/*! Length of error string. */
	unsigned int length_;

	/*! If set then warning messages are displayed when thrown. */
	bool isDisplay_;

	/*! If set then warning number is displayed with warning message. */
	bool isDisplayNumber_;

	/*! Used to pass back last warning to caller. Saves caller having to free memory for warning string. */
	Warning warning_;

	/*! Stack of warning numbers */
	Stack<unsigned int> numbers_;

	/*! Stack of warning strings */
	PointerStack<wchar_t*> strings_;
};

extern Error error;

#endif